"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.decrypter = exports.encrypter = void 0;
const config_1 = require("./config");
const utils_1 = require("./utils");
var factoryMode;
(function (factoryMode) {
    factoryMode["d"] = "decrypt";
    factoryMode["e"] = "encrypt";
})(factoryMode || (factoryMode = {}));
/**
 * 加密
 * @param text 加密的明文
 * @param keys 子密钥组
 * @returns 加密后，16进制字符串
 */
function encrypter(text, keys) {
    // 明文转 Buffer
    const buffer = (0, utils_1.getBuffer)(text);
    const uint8Array = sliceGroup(buffer);
    let result = ''; // 密文
    for (let i = 0; i < uint8Array.length; i++) {
        const buffer = Buffer.concat([uint8Array[i]]);
        const binary = (0, utils_1.HexToBinary)(buffer);
        result += algorithmFactory(binary, keys);
    }
    return result;
}
exports.encrypter = encrypter;
/**
 * 解密
 * @param ciphertext 密文
 * @param keys 子密钥组
 * @returns 解密后的内容
 */
function decrypter(ciphertext, keys) {
    const strArray = sliceGroup(ciphertext);
    let vision = ''; // 解密后的 16 进制数
    strArray.forEach(item => {
        const binary = (0, utils_1.getBinary)(item);
        vision += algorithmFactory(binary, keys, factoryMode.d);
    });
    // 将 vision 转为 Buffer 然后输出 明文 字符
    const arr = [];
    for (let i = 0; i < vision.length; i += 2) {
        const value = vision.substring(i, i + 2);
        arr.push(parseInt('0x' + value));
    }
    const uint8Arr = new Uint8Array(arr);
    const buffer = Buffer.concat([uint8Arr]);
    return buffer.toString();
}
exports.decrypter = decrypter;
/**
 * 123
 * @param data Buffer 数据
 * @param limit
 * @returns
 */
function sliceGroup(data) {
    if (Buffer.isBuffer(data) === true) {
        const limit = 8; // Buffer 数据每一项存在2个16进制数，故拿取64b的数据只需拿 8项
        const result = [];
        const newBuffer = Uint8Array.prototype.slice.call(data);
        for (let i = 0; i < newBuffer.length / 8; i++) {
            const item = newBuffer.slice(i * limit, i * limit + limit);
            result.push(item);
        }
        return result;
    }
    else if (typeof data === 'string') {
        const limit = 16; // 16进制字符串，每一项是一个16进制数，故拿取64b,需要拿16项 
        let result = [];
        for (let i = 0; i < data.length / limit; i++) {
            const item = data.substring(i * limit, i * limit + limit);
            result.push(item);
        }
        return result;
    }
    return [''];
}
/**
 * 算法工厂
 * @param binary 二进制数
 * @param subKeys 子密钥组
 * @param mode 模式，加密 | 解密模式
 * @returns
 */
function algorithmFactory(binary, subKeys = [], mode = factoryMode.e) {
    // IP 置换
    const ip = (0, utils_1.permutation)(binary, config_1.IP_TABLE);
    const ipL = ip.substring(0, ip.length / 2);
    const ipR = ip.substring(ip.length / 2);
    const f_iteration = f_iteration_16(ipL, ipR, subKeys, mode);
    let finalResult = (0, utils_1.permutation)(f_iteration, config_1.P_TABLE_T);
    finalResult = (0, utils_1.binaryToHex)(finalResult);
    return finalResult;
}
/**
 * 16 轮 f 函数迭代
 * @param L
 * @param R
 */
function f_iteration_16(L0, R0, subKeys = [], mode = factoryMode.e) {
    const arr = [];
    for (let i = 0; i < 16; i++) {
        const k = mode === factoryMode.e ? subKeys[i] : subKeys[15 - i]; // 这一次迭代 对应的子密钥
        let L = '';
        let R = '';
        if (i !== 0) {
            // 其他 次
            L = arr[i - 1].R;
            const f_result = f(arr[i - 1].R, k);
            R = XOR(arr[i - 1].L, f_result);
        }
        else {
            // 第一次
            L = R0;
            const f_result = f(R0, k);
            R = XOR(L0, f_result);
        }
        arr.push({
            L,
            R
        });
    }
    return arr[arr.length - 1].R + arr[arr.length - 1].L;
}
/**
 * 亦或运算，相同为0，否则为1
 * @param ER
 * @param K 子密钥
 * @returns
 */
function XOR(ER, K) {
    let result = '';
    for (let i = 0; i < ER.length; i++) {
        const r = ER.substring(i, i + 1);
        const k = K.substring(i, i + 1);
        result += r === k ? '0' : '1';
    }
    return result;
}
// f 函数
function f(R, K) {
    // # 1 E 扩展
    const ER = (0, utils_1.permutation)(R, config_1.E_TABLE);
    // # 2 异或 运算
    const xor = XOR(ER, K);
    // # 3 放入 s-box 处理
    const sbox = SBOX(xor);
    // # 4 对S盒的输出结果进行 P 转换
    const result = (0, utils_1.permutation)(sbox, config_1.P_TABLE);
    return result;
}
// SBOX 运算
function SBOX(b) {
    // 分组
    const group = [];
    for (let i = 0; i < b.length / 6; i++) {
        const item = b.substring(i * 6, i * 6 + 6);
        group.push(item);
    }
    let s = '';
    group.forEach((item, index) => {
        const rowIndex = +(item.substring(0, 1)) * 2 + (+item.substring(item.length - 1));
        const colIndex = (0, utils_1.to10)(item.substring(1, item.length - 1));
        const result = config_1.SBOX_TABLE[index][rowIndex][colIndex];
        s += (0, utils_1.to2)(result);
    });
    return s;
}
function combine(a, b) {
    if (typeof a === "number" && typeof b === "number") {
        return a * b;
    }
    else if (typeof a === "string" && typeof b === "string") {
        return a + b;
    }
    throw new Error("type different a and b ");
}
// combine()
